#include "readini.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "pjsua.h"

int readIni(const char *filename, Account *account, Settings *settings) {
    FILE *file = fopen(filename, "r");
    if (file == NULL) {
        perror("Error opening file");
        return -1;
    }

    char line[1024];
    char key[MAX_STRING_LENGTH], value[MAX_STRING_LENGTH];
    int isAccount = 1; // 标记当前解析的是Account还是Settings

    while (fgets(line, sizeof(line), file)) {
        // 去除行尾的换行符
        line[strcspn(line, "\n")] = 0;

        // 检查是否是新的section
        if (line[0] == '[') {
            if (strncmp(line + 1, "Account", 7) == 0) {
                isAccount = 1;
            } else if (strncmp(line + 1, "Settings", 8) == 0) {
                isAccount = 0;
            }
            continue;
        }

        // 解析键值对
        // scan a line which is key=value


        if (sscanf(line, "%[^=]=%[^\n]", key, value) == 2) { // 确保读取到两个字段，并且value包含等号后面的所有内容
            if (isAccount) {
                if (strcmp(key, "label") == 0 && strlen(value) > 0) {
                    strncpy(account->label, value, MAX_STRING_LENGTH - 1);
                    account->label[MAX_STRING_LENGTH - 1] = '\0';
                } else if (strcmp(key, "server") == 0 && strlen(value) > 0) {
                    strncpy(account->server, value, MAX_STRING_LENGTH - 1);
                    account->server[MAX_STRING_LENGTH - 1] = '\0';
                } else if (strcmp(key, "proxy") == 0 && strlen(value) > 0) {
                    char *token = strtok(value, ",");
                    while (token != NULL && account->num_proxies < MAX_PROXIES) {
                        strncpy(account->proxies[account->num_proxies], token, MAX_STRING_LENGTH - 1);
                        account->proxies[account->num_proxies][MAX_STRING_LENGTH - 1] = '\0';
                        token = strtok(NULL, ",");
                        account->num_proxies++;
                    }
                } else if (strcmp(key, "domain") == 0 && strlen(value) > 0) {
                    strncpy(account->domain, value, MAX_STRING_LENGTH - 1);
                    account->domain[MAX_STRING_LENGTH - 1] = '\0';
                } else if (strcmp(key, "username") == 0 && strlen(value) > 0) {
                    strncpy(account->username, value, MAX_STRING_LENGTH - 1);
                    account->username[MAX_STRING_LENGTH - 1] = '\0';
                } else if (strcmp(key, "authID") == 0 && strlen(value) > 0) {
                    strncpy(account->authID, value, MAX_STRING_LENGTH - 1);
                    account->authID[MAX_STRING_LENGTH - 1] = '\0';
                } else if (strcmp(key, "password") == 0 && strlen(value) > 0) {
                    strncpy(account->password, value, MAX_STRING_LENGTH - 1);
                    account->password[MAX_STRING_LENGTH - 1] = '\0';
                } else if (strcmp(key, "displayName") == 0 && strlen(value) > 0) {
                    strncpy(account->displayName, value, MAX_STRING_LENGTH - 1);
                    account->displayName[MAX_STRING_LENGTH - 1] = '\0';
                } else if (strcmp(key, "transport") == 0 && strlen(value) > 0) {
                    strncpy(account->transport, value, MAX_STRING_LENGTH - 1);
                    account->transport[MAX_STRING_LENGTH - 1] = '\0';
                } else if (strcmp(key, "registerRefresh") == 0 && strlen(value) > 0) {
                    account->registerRefresh = atoi(value);
                } else if (strcmp(key, "keepAlive") == 0 && strlen(value) > 0) {
                    account->keepAlive = atoi(value);
                } else if (strcmp(key, "allowRewrite") == 0 && strlen(value) > 0) {
                    account->allowRewrite = (strcmp(value, "true") == 0) ? PJ_TRUE : PJ_FALSE;
                } else if (strcmp(key, "ice") == 0 && strlen(value) > 0) {
                    account->ice = (strcmp(value, "true") == 0) ? PJ_TRUE : PJ_FALSE;
                }
            } else {
                if (strcmp(key, "userAgent") == 0 && strlen(value) > 0) {
                    strncpy(settings->userAgent, value, MAX_STRING_LENGTH - 1);
                    settings->userAgent[MAX_STRING_LENGTH - 1] = '\0';
                } else if (strcmp(key, "audioInputDevice") == 0 && strlen(value) > 0) {
                    strncpy(settings->audioInputDevice, value, MAX_STRING_LENGTH - 1);
                    settings->audioInputDevice[MAX_STRING_LENGTH - 1] = '\0';
                } else if (strcmp(key, "audioOutputDevice") == 0 && strlen(value) > 0) {
                    strncpy(settings->audioOutputDevice, value, MAX_STRING_LENGTH - 1);
                    settings->audioOutputDevice[MAX_STRING_LENGTH - 1] = '\0';
                } else if (strcmp(key, "vad") == 0 && strlen(value) > 0) {
                    settings->vad = (strcmp(value, "true") == 0) ? PJ_TRUE : PJ_FALSE;
                } else if (strcmp(key, "ec") == 0 && strlen(value) > 0) {
                    settings->ec = (strcmp(value, "true") == 0) ? PJ_TRUE : PJ_FALSE;
                } else if (strcmp(key, "opusStereo") == 0 && strlen(value) > 0) {
                    settings->opusStereo = (strcmp(value, "true") == 0) ? PJ_TRUE : PJ_FALSE;
                } else if (strcmp(key, "forceCodec") == 0 && strlen(value) > 0) {
                    settings->forceCodec = (strcmp(value, "true") == 0) ? PJ_TRUE : PJ_FALSE;
                } else if (strcmp(key, "audioCodecs") == 0 && strlen(value) > 0) {
                    char *token = strtok(value, ",");
                    while (token != NULL && settings->num_audioCodecs < MAX_AUDIO_CODECS) {
                        strncpy(settings->audioCodecs[settings->num_audioCodecs], token, MAX_STRING_LENGTH - 1);
                        settings->audioCodecs[settings->num_audioCodecs][MAX_STRING_LENGTH - 1] = '\0';
                        token = strtok(NULL, ",");
                        settings->num_audioCodecs++;
                    }
                } else if (strcmp(key, "disableVideo") == 0 && strlen(value) > 0) {
                    settings->disableVideo = (strcmp(value, "true") == 0) ? PJ_TRUE : PJ_FALSE;
                } else if (strcmp(key, "rport") == 0 && strlen(value) > 0) {
                    settings->rport = (strcmp(value, "true") == 0) ? PJ_TRUE : PJ_FALSE;
                } else if (strcmp(key, "sourcePort") == 0 && strlen(value) > 0) {
                    settings->sourcePort = atoi(value);
                } else if (strcmp(key, "rtpPortMin") == 0 && strlen(value) > 0) {
                    settings->rtpPortMin = atoi(value);
                } else if (strcmp(key, "rtpPortMax") == 0 && strlen(value) > 0) {
                    settings->rtpPortMax = atoi(value);
                } else if (strcmp(key, "enableSTUN") == 0 && strlen(value) > 0) {
                    settings->enableSTUN = (strcmp(value, "true") == 0) ? PJ_TRUE : PJ_FALSE;
                } else if (strcmp(key, "STUN") == 0 && strlen(value) > 0) {
                    char *token = strtok(value, ",");
                    while (token != NULL && settings->num_STUN < MAX_STUN_SERVERS) {
                        strncpy(settings->STUN[settings->num_STUN], token, MAX_STRING_LENGTH - 1);
                        settings->STUN[settings->num_STUN][MAX_STRING_LENGTH - 1] = '\0';
                        token = strtok(NULL, ",");
                        settings->num_STUN++;
                    }
                } else if (strcmp(key, "enableDNS") == 0 && strlen(value) > 0) {
                    settings->enbaleDNS = (strcmp(value, "true") == 0) ? PJ_TRUE : PJ_FALSE;
                } else if (strcmp(key, "DNS") == 0 && strlen(value) > 0) {
                    char *token = strtok(value, ",");
                    while (token != NULL && settings->num_DNS < MAX_STUN_SERVERS) {
                        strncpy(settings->DNS[settings->num_DNS], token, MAX_STRING_LENGTH - 1);
                        settings->DNS[settings->num_DNS][MAX_STRING_LENGTH - 1] = '\0';
                        token = strtok(NULL, ",");
                        settings->num_DNS++;
                    }
                } else if (strcmp(key, "enableLog") == 0 && strlen(value) > 0) {
                    settings->enableLog = (strcmp(value, "true") == 0) ? PJ_TRUE : PJ_FALSE;
                } else if (strcmp(key, "logPath") == 0 && strlen(value) > 0) {
                    strcpy(settings->logPath, value);
                }
            }
        }
    }
}

void printAccount(Account *account) {
    printf("Account:\n");
    printf("  label: %s\n", account->label);
    printf("  server: %s\n", account->server);
    printf("  proxies: ");
    for (int i = 0; i < account->num_proxies; i++) {
        printf("%s ", account->proxies[i]);
    }
    printf("\n");
    printf("  domain: %s\n", account->domain);
    printf("  username: %s\n", account->username);
    printf("  authID: %s\n", account->authID);
    printf("  password: %s\n", account->password);
    printf("  displayName: %s\n", account->displayName);
    printf("  transport: %s\n", account->transport);
    printf("  registerRefresh: %d\n", account->registerRefresh);
    printf("  keepAlive: %d\n", account->keepAlive);
    printf("  allowRewrite: %d\n", account->allowRewrite);
    printf("  ice: %d\n", account->ice);

}

void printSettings(Settings *settings) {
    printf("Settings:\n");
    printf("  userAgent: %s\n", settings->userAgent);
    printf("  audioInputDevice: %s\n", settings->audioInputDevice);
    printf("  audioOutputDevice: %s\n", settings->audioOutputDevice);
    printf("  vad: %d\n", settings->vad);
    printf("  ec: %d\n", settings->ec);
    printf("  opusStereo: %d\n", settings->opusStereo);
    printf("  forceCodec: %d\n", settings->forceCodec);
    printf("  num_audioCodecs: %d\n", settings->num_audioCodecs);
    printf("  audioCodecs: ");
    for (int i = 0; i < settings->num_audioCodecs; i++) {
        printf("%s ", settings->audioCodecs[i]);
    }
    printf("\n");
    printf("  disableVideo: %d\n", settings->disableVideo);
    printf("  rport: %d\n", settings->rport);
    printf("  sourcePort: %d\n", settings->sourcePort);
    printf("  rtpPortMin: %d\n", settings->rtpPortMin);
    printf("  rtpPortMax: %d\n", settings->rtpPortMax);
    printf("  enableSTUN: %d\n", settings->enableSTUN);
    printf("  num_STUN: %d\n", settings->num_STUN);
    for (int i = 0; i < settings->num_STUN; i++) {
        printf("  STUN[%d]: %s\n", i, settings->STUN[i]);
    }    
    printf("  enbaleDNS: %d\n", settings->enbaleDNS);
    printf("  num_DNS: %d\n", settings->num_DNS);
    for (int i = 0; i < settings->num_DNS; i++) {
        printf("  DNS[%d]: %s\n", i, settings->DNS[i]);
    }
    printf("  enableLog: %d\n", settings->enableLog);
    printf("  logPath: %s\n", settings->logPath);
}
